package item25;

import java.util.ArrayList;
import java.util.List;

/**
 * 第25条：列表优先于数组
 */
public class Main01 {

    public static void main(String[] args) {
        // fails at runtime!
        // 失败在运行时
        Object[] objectArray = new Long[1];
        objectArray[0] = "i don't fit in"; // Throws ArrayStoreException  抛异常

        // won't compile
        // 不会编译
        // List<Object> ol = new ArrayList<Long>(); // incompatible types 不兼容的类型
        // ol.add("i don't fit in");

        // why generic array creation is illegal - won't compile!
        // 为什么集合数组创建是非法的 - 不会编译
//        List<String>[] stringLists = new ArrayList<String>[1];
//        List<Integer> intList = Arrays.asList(42);
//        Object[] objects = stringLists;
//        objects[0] = intList;
//        String s = stringLists[0].get(0);



    }

    // reduction without generics, and with concurrency flaw!
    // 没有泛型的减少方法，与并发问题
    static Object reduce01(List list, Function01 f, Object initVal) {
        synchronized (list) {
            Object result = initVal;
            for (Object o : list)
                result = f.apply(result, o);
            return result;
        }
    }

    static Object reduce02(List<?> list, Function01 f, Object initVal) {
        Object[] snapshot = list.toArray(); // locks list internally
        Object result = initVal;
        for (Object e : snapshot)
            result = f.apply(result, e);
        return result;
    }

    // naive generic version of reduction - won't compile!
    // 不会编译
    static <E> E reduce03(List<E> list, Function02<E> f, E initVal) {
        E[] snapshot = (E[]) list.toArray(); // locks list internally 内部锁列表
        E result = initVal;
        for (E e : snapshot)
            result = f.apply(result, e);
        return result;
    }

    // list-based generic reduction
    // 基于列表的通用减少方法
    static <E> E reduce04(List<E> list, Function02<E> f, E initVal) {
        List<E> snapshot;
        synchronized (list) {
            snapshot = new ArrayList<E>(list);
        }
        E result = initVal;
        for (E e : snapshot)
            result = f.apply(result, e);
        return result;
    }

}
